<?php
namespace app\client\controller\pay\alipay;
use Pay\Pay;
use think\db\Expression;

class H5Controller extends \think\Controller {
  /**
   *  @brief  : 支付宝H5支付
   *  @return : form
   *  @details: http://gg.zf.game654.cn/pay.alipay.h5/apply.html?UserID=28&GoodID=3&KindID=0
   */
  public function ApplyAction() {
    
    $UserID = $this->request->param('UserID/d', 0); // 用户标识
    $GoodID = $this->request->param('GoodID/d', 0); // 商品数组下标, 按面值从小至大, 从0开始
    $KindID = $this->request->param('KindID/d', 0); // 对应小游戏, 0=大厅
    $APPID  = $this->request->param('APPID/s', 'alipay2'); // 用哪个支付宝商户
    $PayType= $this->request->param('PayType/d', 3); // 用哪个支付组
    $Type   = $this->request->param('Type/d', 0); // 用哪个商品组
    $conf = config("pay.{$APPID}");

    if ($UserID <= 0 || $GoodID < 0 || $KindID < 0 || empty($conf) || $PayType < 0) {
      return abort(100, '业务参数输入有误');
    }
    $conf['notify_url'] = url('Notify', '', true, true);
    $conf = ['alipay' => $conf];

    // 确定玩家
    $User = table('AccountsInfo', "rydb.basic")->where(['UserID' => $UserID])->find();
    if (empty($User)) {
      return abort(102, "用户[{$UserID}]不存在");
    }
    
    // 确定商品
    $Goods = table('CardCoin', "rydb.websms")->where(['State' => 1, 'PayType' => $PayType, 'Channel' => $User['Channel'],'Type'=>$Type, 'KindID' => $KindID])->order(['RMB' => 'ASC'])->select();
    if (empty($Goods)) {
      return abort(103, '游戏商品未定义');
    }
    if (empty($Goods[$GoodID])) {
      return abort(104, '该商品不存在');
    }
    $Goods = $Goods[$GoodID];
    
    // 确定订单
    $Price    = sprintf('%.2f', $Goods['RMB']);
    $TradeNo  = MakeTradeNo();

    // 构造回传参数 "UserID,CardID,IP,KindID"
    $params = [$UserID, $Goods['ID'], $this->request->ip(), $KindID];
    $params = implode(',', $params);
    $params = urlencode($params);
    $order = [
      'subject'         => '游戏充值', // 商品的标题/交易标题/订单标题/订单关键字等
      'out_trade_no'    => $TradeNo,  // 商户网站唯一订单号
      'total_amount'    => $Price, // 订单总金额，单位为元，精确到小数点后两位，取值范围[0.01,100000000]
      'passback_params' => $params,
    ];
    $pay = new Pay($conf);
    $eax = $pay->driver('alipay')->gateway('wap')->apply($order);
    echo($eax);
  }
  /**
   *  @brief  : 支付宝异步回调
   *  @return : string('SUCCESS'|'FAILURE')
   *  @details: https://alipay.open.taobao.com/docs/doc.htm?spm=a219a.7629140.0.0.252c4b70DlYKJp&treeId=193&articleId=105286&docType=1#s0
   */
  public function NotifyAction() {

    trace(__METHOD__);
    $data = $this->request->post();
    trace($data);
    
    if (empty($data)) {
      echo('FAILURE');
      return;
    }
    
    // 确定支付宝商户配置
    $cfg = [];
    $APPID = $this->request->param('app_id/s', ''); // 用哪个支付宝商户
    foreach(['alipay', 'alipay2', 'alipay3'] as $val) {
      $eax = config("pay.{$val}");
      if ($eax['app_id'] == $APPID) {
        $cfg['alipay'] = $eax;
        break;
      }
    }
    if (empty($cfg)) {
      trace("支付宝配置[{$APPID}]不存在");
      return;
    }
    // 验证签名是否合法
    $pay = new Pay($cfg);
    $eax = $pay->driver('alipay')->gateway('wap')->verify($data);
    if (empty($eax)) {
      trace('验签失败');
      echo('FAILURE');
      return;
    }
    
    // 验证app_id是否为该商户本身。
    if ($cfg['alipay']['app_id'] != $data['app_id']) {
      trace("app_id验证失败[{$cfg['alipay']['app_id']}]!=[{$data['app_id']}]");
      echo('FAILURE');
      return;
    }
    
    // 验证通知类型
    if (!($data['notify_type'] == 'trade_status_sync' && $data['trade_status'] == 'TRADE_SUCCESS')) {
      trace('`notify_type`和`trade_status`不匹配');
      echo('FAILURE');
      return;
    }
/*
[2019-04-12 15:24:46] 110.75.248.54 POST /pay.alipay.h5/notify.html
[ log ] app\client\controller\pay\alipay\H5Controller::NotifyAction
[ log ] array (
  'gmt_create' => '2019-04-12 15:01:11',
  'charset' => 'utf-8',
  'seller_email' => 'jjc0005@126.com',
  'subject' => '游戏充值',
  'sign' => 'KKmKHq5FGO5FleCo9FNk/NRo2MwVojm4Lj4iUbB1trynvmvk75HQ1W4E9ur1TmqPdOEJldHe3AF8D8x1K8sMAGeNSx7xQHoqfLrZdNKf4ffw5atLihIvGLuSveGb2/DbWeHCOVaJFqxwuBMoYAvAAF9JB19fvei/tQhqWHVWJs+Aou+zDioIykAWdkDFnMGeM7YzY5/Ppkvl3ci6USVNrcXJSpvCheloUlnZBonkxSrpE6qW8p115C5KR9OIM3N7DE46gofvofXz84thlqhWmhzprR3YK2s86pMa6PmpeZkhsvyJQr33PkDMNN+cL68kfLXrMFWpp+sjTozGpsiTvQ==',
  'buyer_id' => '2088112697321750',
  'notify_id' => '2019041200222151030021751012041908',
  'notify_type' => 'trade_status_sync',
  'trade_status' => 'TRADE_CLOSED',
  'app_id' => '2016052801453658',
  'sign_type' => 'RSA2',
  'seller_id' => '2088121766486397',
  'gmt_payment' => '2019-04-12 15:01:12',
  'notify_time' => '2019-04-12 15:24:40',
  'gmt_refund' => '2019-04-12 15:10:29.890',
  'out_biz_no' => '201904121500570207',
  'passback_params' => '2,149,122.235.225.142,0',
  'version' => '1.0',
  'out_trade_no' => '201904121500570207',
  'total_amount' => '20.00',
  'refund_fee' => '20.00',
  'trade_no' => '2019041222001421751035394175',
  'auth_app_id' => '2016052801453658',
  'buyer_logon_id' => '139****4376',
  'gmt_close' => '2019-04-12 15:10:29',
)
[ log ] `notify_type`和`trade_status`不匹配
*/

    
    // 解析回传参数 "UserID,CardID,IP,KindID"
    $params = empty($data['passback_params']) ? '' : $data['passback_params'];
    $params = explode(',', $params);
    $params = empty($params) ? [] : $params;
    
    $UserID   = empty($params[0]) ? 0 : $params[0] * 1;
    $CardID   = empty($params[1]) ? 0 : $params[1] * 1;
    $ClientIP = empty($params[2]) ? '' : $params[2];
    $KindID   = empty($params[3]) ? 0 : $params[3] * 1; // 从下单请求中传入

    if ($CardID < 0 || $UserID <= 0 || $KindID < 0) {
      trace('回传参数丢失或无效');
      echo('FAILURE');
      return;
    }

    try {
      $eax = ChargeUpdate(1, $UserID, $CardID, $ClientIP, $KindID, $data['out_trade_no'], $data['trade_no'], $data['total_amount']);
      echo('SUCCESS');
    } catch (Exception $e) {
      $errno = $e->getCode();
      $error = $e->getMessage();
      trace(['errno' => $errno, 'error' => $error]);
      echo('FAILURE');
    }
    return;
  }

  /**
   *  @brief  : 支付宝APP支付退款
   *  @return : none
   *  @details: php index.php client/pay.alipay.h5/Refund
   */
  public function RefundAction() {
    var_dump(__METHOD__);

    $out_trade_no = '201904131722198999';
    
    $conf = ['alipay' => config('pay.alipay2')];
    $pay = new Pay($conf);
    $eax = $pay->driver('alipay')->gateway('wap')->find($out_trade_no);
    print_r($eax);

    printf('是否继续退款?[y/n]');
    $input = fgets(STDIN);
    if ($input === false) {
      return;
    }
    $input = strtolower($input[0]);
    if (!in_array($input, ['y', "\n"])) {
      return;
    }

    $eax = $pay->driver('alipay')->gateway('wap')->refund($out_trade_no, $eax['total_amount']);
    print_r($eax);
    
    $eax = $pay->driver('alipay')->gateway('wap')->find($out_trade_no);
    print_r($eax);
    
  }
}
